﻿ /*
  *              功能:基于msp430的电视机显示驱动程序.
  *
  *              作者：林中鸟
  *
  *              版权:本软件为自由软件，基于GPL许可协议,你可以自由修改和发布.期望它能对你有所益处.
  *               
  *              最后修正时间：2009/4/28
  *              
  *              版权所有：中文中国
  */
 
#include "Ascii5x8.h"
#include "msp430x42x.h"

#define SCREENTOP 100           //电视最顶的一条线
#define SCREENBOT 180          //电视最底的一条线

#define PORT_SYNC_DIR    P2DIR
#define PORT_SYNC_OUT    P2OUT

#define PORT_WHITE_DIR   P1DIR
#define PORT_WHITE_OUT   P1OUT

#define PORT_SYNC_BIT    BIT2
#define PORT_WHITE_BIT   BIT0

#define BYTE_ASCII       (5)     // 一个ASCII点阵的模的字节 = 宽 * 高 / 8

extern OutPixel(char vl1,char vl2,char vl3,char vl4,char vl5,char vl6,char vl7,char vl8);

char screen[(SCREENBOT - SCREENTOP)/2*8];            //显存
char syncON, syncOFF; 
//当前屏幕的扫描行
int  screen_i;
//当前屏幕的扫描行
unsigned short line;


/**********************************************************
 *函数名：DisplayInit
 *功能：显示初始化
 *入口参数：无
 *出口参数：无
 *说明：看其函数名可能会认为是对屏幕进行初始化,其实这样命名也
 *    是没有办法的,因为没有比它更好的了,它其实是对显示数据的
 *    输出设备进行初始化
 **********************************************************/
void DisplayInit(void)
{ 
    syncON =0x00;
    syncOFF=0x04; 
    
    line=1;
    
    PORT_SYNC_DIR  |= PORT_SYNC_BIT;             // 脉冲输出端口
    PORT_WHITE_DIR |= PORT_WHITE_BIT;           //白色电平输出端口
    P1IE = 0;
    P2IE = 0;
    PORT_WHITE_OUT = 0X00;                    //WHITE
    PORT_SYNC_OUT  |= PORT_SYNC_BIT;
  
    TACTL  = TASSEL_2 +TACLR+ID_0 + MC_0;     // Timer init SMCLK
    CCR0   = 256;                             // 64us using a 4MHz crystal 
    CCTL0  = CCIE;                            // Enables CCR0 interupt or video line interrupt
    CCTL1  = 0;
    CCTL2  = 0;
    _EINT();                                  // enable interrupts
    screen_i=0;
    TACTL  |= MC0;                             //增计数模式，开始计数
}


/**********************************************************
 *函数名：VideoLocate
 *功能：在屏幕指定位置显示一个点
 *入口参数：x:横坐标 y:纵坐标 c:0-黑色 1-白色 2-反转
 *出口参数：无
 *说明：它只是对显存中的内容进行操作,而不是对屏幕直接进行操作
 **********************************************************/
void VideoLocate(char x, char y, char c)
{
    screen_i=((int)x >> 3) + ((int)y << 3);
    if (c==0)	screen[screen_i] = screen[screen_i] & ~(1<<(x & 0x7)); 
    if (c==1) 	screen[screen_i] = screen[screen_i] | (1<<(x & 0x7)); 
    if (c==2)	screen[screen_i] = screen[screen_i] ^ (1<<(x & 0x7));   
}


/**********************************************************
 *函数名：VideoDisplay
 *功能：将显存中的内容打到屏幕上
 *入口参数：无
 *出口参数：无
 *说明：该函数并不将显存中的所有内容打到屏幕上,而只扫描一行
 *    可以认为是最底层的屏幕驱动了
 **********************************************************/
void VideoDisplay(void){
  
    if(line<SCREENBOT && line>=SCREENTOP) 
    { 
        screen_i=(line-SCREENTOP)<<2 & 0xfff8;
        OutPixel(screen[screen_i],screen[screen_i+1],screen[screen_i+2],screen[screen_i+3],screen[screen_i+4],screen[screen_i+5], screen[screen_i+6],screen[screen_i+7]);
    }
    
}


/**********************************************************
 *函数名：VideoDetect
 *功能：返回屏幕指定坐标处的颜色
 *入口参数：x:横坐标 Y:纵坐标
 *出口参数: 指定坐标处的灰度值 0:黑色 1:白色
 *说明：所取值并不从屏幕直接获取而是通过显存
 **********************************************************/
char VideoDetect(char x, char y){
  
    screen_i=((int)x >> 3) + ((int)y << 3) ;   
    return ( screen[screen_i] & 1<<(x & 0x7));   
    
}


/**********************************************************
函数名：DisplayClear
功能：清除屏幕
入口参数：无
出口参数：无
说明：该函数并不是直接对屏幕进行清除,而是对显存进行清除
**********************************************************/
void DisplayClear(void){
  
  for(unsigned int i=0;i<(SCREENBOT - SCREENTOP)*4;i++)
      screen[i]=0x00;
  
}

/**********************************************************
函数名：DrawImage
功能：显示图像
入口参数：x:横坐标 y:纵坐标 image:图像数据指针 width:图像宽度
          height:图像高度
出口参数：无
说明：与VideoDisplay相比它是比较高一层的驱动,它操作的目标是
      显存,它可以显示所有能够出现在屏幕上的东西,因为这所有的
      东西都可以看作是一幅图像,事实上它们也就是一幅位图,以下
      字母显示函数,汉字显示函数,数字显示函数等都是建立在此函
      函数之上
**********************************************************/
void DrawImage(unsigned short x,unsigned short y,unsigned char 
               const *image,unsigned short width,unsigned short height){
                 
  unsigned short row,clum,bit_j,temp,temp_x,temp_y;    // 模在字库中的启始位置
  for(row=0;row<height;row++)
  {  
    for(clum=0;clum<width;clum++)
    {
       temp_x=x+clum;
       temp=image[clum];
       temp_y=y+row*8;
       for(bit_j=0;bit_j<8;bit_j++)
       {
         if(temp & 0x80){
           VideoLocate(temp_x,temp_y,1);
         }else{            
           VideoLocate(temp_x,temp_y,0); 
          }
        temp = temp<<1;
        temp_y++;        
        } 
    }
    image+=width;
  }
  
}


/**********************************************************
函数名：Display_Chinese
功能：显示图像
入口参数：hdc:设备句柄
出口参数：无
说明：与上不同，它主要用于对处理后的图像的数据的显示
**********************************************************/
void DisplayChinese(unsigned int UniCode, unsigned char y_pos, unsigned char x_pos){

}


/**********************************************************
函数名：Video_DisplayAscii
功能：显示图像
入口参数：hdc:设备句柄
出口参数：无
说明：与上不同，它主要用于对处理后的图像的数据的显示
**********************************************************/
void VideoDisplayAscii(char x, char y, char ch){
  
  DrawImage(x,y,chardot[ch-0x20],5,1);
  
}


/**********************************************************
函数名：Display_String
功能：显示图像
入口参数：hdc:设备句柄
出口参数：无
说明：与上不同，它主要用于对处理后的图像的数据的显示
**********************************************************/
void DisplayString(unsigned char const *p, unsigned char y_pos, unsigned char x)
{
 
}


/**********************************************************
函数名：VideoLine
功能：显示图像
入口参数：hdc:设备句柄
出口参数：无
说明：与上不同，它主要用于对处理后的图像的数据的显示
**********************************************************/

void VideoLine(char x1, char y1, char x2, char y2, char c){
  
	float x,y,k,m;
	
        k = (float)( y2 -y1)/(float)(x2-x1);
        m = (float)y1 - k * (float)x1 ;
        
        for(x=x1;x<=x2;x=x+ 0.5)
        {
           y = k*x + m;
          VideoLocate((char)x,(char)y,c) ; 
        }
	
}

// CCO 中断服务
#pragma vector = TIMERA0_VECTOR
__interrupt void CC0_IRQ(void)
{ 
    PORT_SYNC_OUT = syncON;      //同步脉冲
    line++; 

    if(line == 298)                //这个值不不固定的
    {           
        syncON  = 0x04;
        syncOFF = 0x00;
    }  
    
    if(line==301)	 //这个值不固定的
    {
        syncON  = 0x00;
        syncOFF = 0x04;
    }
   
    if(line==313) 
    {
        line =1; 
    }
    LPM0_EXIT;
    PORT_SYNC_OUT = syncOFF; 
}
